import type { ComponentInternalInstance, Ref } from 'vue'
import type { TableProps, ColumnType } from '../types'

import { ref } from 'vue'

const useResize = (
  props: TableProps,
  virtualized: ComponentInternalInstance,
  columnsWidthRef: Ref<Record<string, number>>
) => {
  const resizeProxyVisible = ref(false)
  const draggingColumn = ref<ColumnType | null>(null)
  const dragging = ref(false)
  const dragState = ref<any>({})

  const { border } = props

  const getMinWidth = (column: ColumnType) => {
    let width = 40
    if (typeof column.minWidth === 'number') {
      if (column.minWidth > 40) {
        width = column.minWidth
        if (column.minWidth > column.width) {
          width = column.width
        }
      }
    }
    return width
  }
  const getMaxWidth = (column: ColumnType) => {
    if (column.maxWidth && column.maxWidth > getMinWidth(column)) {
      return column.maxWidth > column.maxWidth ? column.width : column.width
    }
    return 0
  }

  const handleMousedown = (event: MouseEvent, column: ColumnType) => {
    if (
      !column ||
      !column.resizable ||
      typeof column.width !== 'number' ||
      column.width < 40 ||
      (column.children && column.children.length > 0)
    ) {
      return
    }
    if (draggingColumn.value && border) {
      dragging.value = true

      resizeProxyVisible.value = true
      const tableEl = virtualized.vnode.el as HTMLElement
      const tableRect = tableEl.getBoundingClientRect()
      const columnEl = event.target as HTMLDivElement
      const columnRect = columnEl.getBoundingClientRect()
      const minLeft = columnRect.left - tableRect.left + getMinWidth(column)
      const maxWidth = getMaxWidth(column)
      const maxRight = maxWidth ? columnRect.left + maxWidth : maxWidth

      dragState.value = {
        // 鼠标所在位置距离视图左侧距离
        startMouseLeft: event.clientX,
        // 列的右侧距离table左侧距离
        startLeft: columnRect.right - tableRect.left,
        // 列的左侧距离table左侧距离
        startColumnLeft: columnRect.left - tableRect.left,
        // table距离视图左侧距离
        tableLeft: tableRect.left
      }

      const resizeProxy = (virtualized.vnode.el as HTMLElement).querySelector(
        '#resize-proxy'
      ) as HTMLElement
      resizeProxy.style.left = `${dragState.value.startLeft}px`

      document.onselectstart = () => {
        return false
      }
      document.ondragstart = () => {
        return false
      }

      const handleMousemove = (event: MouseEvent) => {
        const deltaLeft = event.clientX - dragState.value.startMouseLeft
        const proxyLeft = dragState.value.startLeft + deltaLeft
        if (maxRight > 0) {
          resizeProxy.style.left = `${Math.min(maxRight, Math.max(minLeft, proxyLeft))}px`
        } else {
          resizeProxy.style.left = `${Math.max(minLeft, proxyLeft)}px`
        }
      }

      const handleMouseup = () => {
        if (dragging.value) {
          const { startColumnLeft } = dragState.value
          const finalLeft = Number.parseInt(resizeProxy.style.left, 10)
          const columnWidth = finalLeft - startColumnLeft
          columnsWidthRef.value[column.field] = columnWidth
          virtualized.exposed?.resetMeasuredIndices()

          document.body.style.cursor = ''
          dragging.value = false
          draggingColumn.value = null
          dragState.value = {}
          resizeProxyVisible.value = false
        }

        document.removeEventListener('mousemove', handleMousemove)
        document.removeEventListener('mouseup', handleMouseup)
        document.onselectstart = null
        document.ondragstart = null
      }

      document.addEventListener('mousemove', handleMousemove)
      document.addEventListener('mouseup', handleMouseup)
    }
  }

  const handleMousemove = (event: MouseEvent, column: ColumnType) => {
    if (
      !column ||
      !column.resizable ||
      typeof column.width !== 'number' ||
      column.width < 40 ||
      (column.children && column.children.length > 0)
    ) {
      return
    }
    const el = event.target as HTMLElement
    if (!el || !(el instanceof Element)) {
      return
    }
    /**
     * header cell
     */
    const target = el.closest('div.virtualized-grid-cell') as HTMLElement
    if (!dragging.value && border) {
      const rect = target.getBoundingClientRect()

      const bodyStyle = document.body.style
      if (rect.width >= 40 && rect.right - event.pageX < 8) {
        draggingColumn.value = column
        bodyStyle.cursor = 'col-resize'
      } else {
        bodyStyle.cursor = ''
        draggingColumn.value = null
      }
    }
  }

  const handleMouseout = () => {
    document.body.style.cursor = ''
  }

  return { resizeProxyVisible, handleMousedown, handleMousemove, handleMouseout }
}

export default useResize
